<?php
/**
 * Created by PhpStorm.
 * User: admin
 * Date: 2019/11/5
 * Time: 14:07
 */
namespace app\api\service;

use app\adminapiv3\service\module_manage\netfilter\NetfilterService;
use app\common\definition\InternetProtocolsDefinition;
use app\common\model\access_log\HostAccessLogModel;
use app\common\netfilter\Rule;
use app\common\service\ServerDownload;
use think\Db;

class Export
{
    public $limit = 2;//一次性查询条数

    /**
     * @name 导出防火墙日志
     * @param $info
     * @author wx
     * @date 2019/11/5 15:06
     */
    public function netfilterLog($info)
    {
        //创建目录--标题处理
        $path = '../runtime/Download/netfilterLog/';//生成日志文件
        file_exists($path)? :mkdir($path);
        $csv_header = array(
            '序号',
            '主机id',
            '来源ip',
            '目标ip',
            '方向',
            '目标端口',
            '端口类型',
            '是否授权访问',
            '首次访问时间',
            '最后访问时间',
            '是否忽略',
            '是否伪装端口',
            '访问总数',
        );
        $header = implode(',', $csv_header) . PHP_EOL;
        $header = iconv('UTF-8','GBK',$header);
        $host_arr = explode(',', $info['host_id']);
        $host_count = count($host_arr);

        //修改状态
        Db::name('server_download')->where(['id' => $info['id']])->update(['status' => 1]);


        $index = 1;
        //访问日志模型
        $logModel = new HostAccessLogModel();

        //查询数据 --循环主机
        foreach ($host_arr as $value){
            $ip = Db::name('host_contact')->where('host_id',$value)->value('ip');
            $ipArr[] = $ip;
            //数据库连接
            $logModel->setHostId($value);
            $db = $logModel;

            //时间筛选
            if($info['end_time'] != 0){
                $db->where('last_time','between', [$info['start_time'], $info['end_time']]);
            }elseif($info['start_time'] != 0 && $info['end_time'] == 0){
                $db->where('last_time','>=', $info['start_time']);
            }

            //寻找数据
            // 打开文件资源，不存在则创建
            $file_name = $path.$ip.'.csv';
            $fp = fopen($file_name,'w');
            fwrite($fp, $header);//写入标题
            $page = 0;//当前页数
            $num = 1;//序号
            do{
                $offset = $page * $this->limit;
                $list = $db->where('host_id',$value)
                    ->field('syslog, elk', true)
                    ->order('id desc')
                    ->limit($offset, $this->limit)
                    ->select();

                if($list){
                    // 处理内容
                    $content = '';
                    foreach ($list as $v) {
                        array_unshift($v, $num);
                        unset($v['id']);
                        if($v['direction'] == 1){
                            $v['direction'] = '出站';
                        }else{
                            $v['direction'] = '入站';
                        }
                        if($v['protocols'] == InternetProtocolsDefinition::TCP_PROTOCOL){
                            $v['protocols'] = 'tcp';
                        }else{
                            $v['protocols'] = 'udp';
                        }
                        if($v['permission'] == 0){
                            $v['permission'] = '未授权';
                        }else{
                            $v['permission'] = '授权';
                        }
                        if($v['ignore'] == 0){
                            $v['ignore'] = '不忽略';
                        }else{
                            $v['ignore'] = '忽略';
                        }
                        if($v['guise'] == 0){
                            $v['guise'] = '不是';
                        }else{
                            $v['guise'] = '是';
                        }
                        $v['first_time'] = date('Y年m月d日 H:i:s', $v['first_time']);
                        $v['last_time'] = date('Y年m月d日 H:i:s', $v['last_time']);
                        $content .= implode(',', $v) . PHP_EOL;
                        $num++;
                    }
                    $content = iconv('UTF-8','GBK',$content);//改变编码
                    // 写入并关闭资源
                    fwrite($fp, $content);
                    $page++;
                }
            }while($list);

            fclose($fp);
            $rate = round($index/$host_count,2) * 100;
            //更新进度状态

            Db::name('server_download')->where(['id' => $info['id']])->update(['ratio' => $rate]);

            $index++;
        }

        //生成压缩包
        $downloadPath = 'download/netfilterLog/'.date('Y-m-d').'/';
        $this->createZip($ipArr, $info, $downloadPath, $path,'.csv');


        echo 'success';die;
    }

    /**
     * @name 导出规则
     * @param $info
     * @author wx
     * @date 2019/11/5 17:02
     */
    public function rule ($info)
    {
        //1. 修改任务状态
        Db::name('server_download')->where(['id' => $info['id']])->update(['status' => 1]);
        //2. 查询规则

        //3. 处理规则
        //4. 写入文件
        //5. 修改任务状态
        //6. 返回
        $hostId_s = $info['host_id'];
        $hostId_a = explode(',', $hostId_s);
        $allCount = count($hostId_a);

        //创建目录
        $path =  '../runtime/Download/iptableList/';
        file_exists($path) ? : mkdir($path,0777, true);

        $netfilterServer = new NetfilterService();
        $index = 1;
        $host_data = Db::name('host')->whereIn('id', $hostId_a)->column('os', 'id');
        foreach ($host_data as $hostId => $os) {//循环写入文件
            $ip = Db::name('host_contact')->where('host_id',$hostId)->value('ip');

            $ipArr[] = $ip;

            $file_name = $path.$ip.'.txt';

            $fp = fopen($file_name,'w');

            $page = 0;//当前页数
            do{
                $offset = $page * $this->limit;
                $list = Db::name('HostRule')->where('host_id', $hostId)
                    ->order('id desc')
                    ->limit($offset, $this->limit)->select();
                $fid_a = array_column($list, 'fid');
                $hostRuleServer = new \app\common\service\module_manage\netfilter\HostRule();

                $childData = $hostRuleServer->childList($hostId, $fid_a);
                $data = $netfilterServer->processOut($childData);

                $ruleServer = new Rule();
                $logData = $ruleServer->firewallRule($data, $os);//具体日志规则

                if($logData){
                    foreach ($logData as $v) {
                        fwrite($fp, $v.PHP_EOL);
                    }
                    // 写入并关闭资源
                    $page++;
                }
            }while($list);

            fclose($fp);
            $rate = round($index/$allCount,2) * 100;
            //更新进度状态
            Db::name('server_download')->where(['id' => $info['id']])->update(['ratio' => $rate]);
            $index++;
        }


        //下载路径
        $downloadPath = 'download/iptablesRule/'.date('Y-m-d').'/';
        $this->createZip($ipArr, $info,$downloadPath, $path,'.txt');

        echo 'SECCESS';die;
    }

    /**
     * @name 生成压缩包
     * @param $ipArr
     * @param $info
     * @return int|string
     * @author wx
     * @date 2019/11/5 14:22
     */
    public function createZip($ipArr, $info, $downloadPath, $runtimePath, $suffix)
    {
        file_exists($downloadPath)? : mkdir($downloadPath,0777,true);
        $zipName = $downloadPath.$info['id'].'_'.time().'.zip';//zip文件名
        $zip = new \ZipArchive;

        if ($zip->open($zipName, \ZIPARCHIVE::OVERWRITE | \ZIPARCHIVE::CREATE)!==TRUE) {
            return 0;
        }

        //------生成压缩包----
        $files = scandir($runtimePath);
        foreach ($files as $file){
            if($file == '.' || $file == '..'){
                continue;
            }
            $fileName = basename($file, $suffix);
            if (in_array($fileName, $ipArr)) {
                $nowFile = $runtimePath.$fileName.$suffix;//文件位置
                //添加到zip中
                if(file_exists($nowFile)){
                    //将文件添加到zip压缩包中
                    $zip->addFile($nowFile, basename($nowFile));
                }
            }
        }
        $zip->close();//关闭

        $server = new ServerDownload();
        //2成功
        return $server->modify(['id' => $info['id']], ['path' => $zipName, 'ratio' => 100, 'status' => 2]);
    }

}